package br.com.puc.controllers;

import java.util.List;

import br.com.caelum.vraptor.Delete;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Put;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.validator.ValidationMessage;
import br.com.puc.models.Colaborador;
import br.com.puc.models.Projeto;
import br.com.puc.models.annotations.Publico;
import br.com.puc.models.enums.StatusProjeto;
import br.com.puc.repositories.ColaboradorRepository;
import br.com.puc.repositories.ProjetoRepository;

@Resource
public class ProjetoController {

	private final Result result;
	private final ProjetoRepository repository;
	
	private final Validator validator;
	private ColaboradorRepository colaboradorRepository;
	
	public ProjetoController(Result result, ProjetoRepository repository, ColaboradorRepository colaboradorRepository, 
	Validator validator) {
		this.result = result;
		this.repository = repository;
		this.colaboradorRepository = colaboradorRepository;
	
		this.validator = validator;
	}
	
	@Publico
	@Get("/projetos")
	public List<Projeto> index() {
		return repository.findAll();
	}
	
	@Post("/projetos")
	public void create(Projeto projeto, List<Long> participantes) {
		addParticipantesProjeto(projeto, participantes);
		validacaoParticipanteInvalido(projeto);
		validator.validate(projeto);
		validator.onErrorUsePageOf(this).newProjeto();
		repository.create(projeto);
		result.redirectTo(this).index();
	}
	
	@Get("/projetos/new")
	public Projeto newProjeto() {
		result.include("colaboradores", colaboradorRepository.findAll());
		return new Projeto();
	}
	
	@Put("/projetos")
	public void update(Projeto projeto, List<Long> participantes) {
		if (participantes != null && participantes.size() > 0) {
			addParticipantesProjeto(projeto, participantes);
			validacaoParticipanteInvalido(projeto);
		} else {
			Projeto old = repository.find(projeto.getId());
			for (Colaborador participante : old.getParticipantes()) {
				projeto.getParticipantes().add(colaboradorRepository.find(participante.getId()));
			}
		}
		validator.validate(projeto);
		validator.onErrorUsePageOf(this).edit(projeto);
		repository.update(projeto);
		result.redirectTo(this).index();
	}

	private void validacaoParticipanteInvalido(Projeto projeto) {
		List<Colaborador> invalidos = projeto.getParticiantesInvalidos();
		if (invalidos.size() > 0) {
			result.include("colaboradores", colaboradorRepository.findAll());
			StringBuilder msg = new StringBuilder("Os seguintes colaboradores não podem ser adicionados ao projeto: ");
			for (Colaborador colaborador : invalidos) {
				msg.append(colaborador.getNome() + ", ");
			}
			validator.add(new ValidationMessage(msg.toString().substring(0, msg.length() - 2), "erro"));
		}
	}
	
	private void addParticipantesProjeto(Projeto projeto, List<Long> participantes) {
		if (participantes != null) {
			projeto.getParticipantes().clear();
			for (Long idParticipante : participantes) {
				projeto.getParticipantes().add(colaboradorRepository.find(idParticipante));
			}
		}
	}
	
	@Get("/projetos/{projeto.id}/edit")
	public Projeto edit(Projeto projeto) {
		result.include("colaboradores", colaboradorRepository.findAll());
		return repository.find(projeto.getId());
	}

	@Publico
	@Get("/projetos/{projeto.id}")
	public Projeto show(Projeto projeto) {
		return repository.find(projeto.getId());
	}

	@Delete("/projetos/{projeto.id}")
	public void destroy(Projeto projeto) {
		repository.destroy(repository.find(projeto.getId()));
		result.redirectTo(this).index();  
	}
	
	@Post("/projetos/iniciar/{projeto.id}")
	public void iniciar(Projeto projeto) {
		projeto = repository.find(projeto.getId());
		if (projeto.podeSerIniciado()) {
			projeto.setStatus(StatusProjeto.EM_ANDAMENTO);
			repository.update(projeto);
			result.include("mensagem", "Projeto iniciado com sucesso!");
		}
		else
			result.include("mensagem", "Atenção: o projeto selecionado não pode ser iniciado. Preencha todos os dados básicos ou verifique se algum usuario atende os requisitos!");
		
		result.redirectTo(this).index();  
	}
	
	@Post("/projetos/concluir/{projeto.id}")
	public void concluir(Projeto projeto) {
		projeto = repository.find(projeto.getId());
		if (projeto.podeSerConcluido()) {
			projeto.setStatus(StatusProjeto.CONCLUIDO);
			repository.update(projeto);
			result.include("mensagem", "Projeto concluído com sucesso!");
		}
		else
			result.include("mensagem", "Atenção: o projeto selecionado não pode ser concluído. O projeto deve estar iniciado e deve possuir, no mínimo, uma publicação associada.");
		
		result.redirectTo(this).index();  
	}
}